package com.logistics.utils.interceptor;

import com.alibaba.fastjson.JSONObject;
import com.logistics.utils.bean.UserBean;
import com.logistics.utils.configure.Configure;
import com.logistics.utils.exception.JwtTimeoutException;
import com.logistics.utils.exception.RenewalException;
import com.logistics.utils.jwt.JwtRegistry;
import com.logistics.utils.redis.RedisService;
import com.logistics.utils.security.EncryptionUtils;
import com.logistics.utils.tool.StringUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Slf4j
@Component
@ConditionalOnProperty(name = {"configure.filter"}, matchIfMissing = true)
public class AuthorizationInterceptor implements HandlerInterceptor {

    @Autowired
    private RedisService redisService;

    @Autowired
    private JwtRegistry jwtRegistry;

    @Autowired
    private Configure configure;

    @Autowired
    public ApplicationContext applicationContext;

    @Autowired
    private CacheManager cacheManager;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = StringUtils.isNotNull(request.getHeader("token")) ? request.getHeader("token") :
                request.getParameter("token");
        if(StringUtils.isNull(token)){
            throw new JwtTimeoutException();
        }
        try {
            jwtRegistry.parseJWT(token);
        }catch (ExpiredJwtException e){
            String refreshToken = configure.getRedisGate() ? redisService.getString(token) :
                    getRefreshToken(token);
            try {
                if(StringUtils.isNull(refreshToken)){
                    throw new JwtTimeoutException();
                }
                Claims claims = jwtRegistry.parseJWT(refreshToken);
                String subject = claims.getSubject();
                // 生产新token
                String newToken = jwtRegistry.createToken(subject);
                long longTime = configure.getToken().getLongTime();
                if(configure.getRedisGate()){
                    redisService.deleteKey(token);
                    redisService.set(newToken, jwtRegistry.createToken(subject, longTime), longTime);
                }else{
                    Cache cache = cacheManager.getCache("cache");
                    cache.evict(token);
                    cache.put(newToken, jwtRegistry.createToken(subject, longTime));
                }
                throw new RenewalException(newToken);
            }catch (ExpiredJwtException e1){
                throw new JwtTimeoutException();
            }
        }
        return true;
    }

    /**
     * 获取spring boot 缓存
     * @return
     */
    private String getRefreshToken(String tokenKey){
        Cache cache = cacheManager.getCache("cache");
        if(StringUtils.isNull(cache.get(tokenKey))){
            return null;
        }
        Object refreshToken = cache.get(tokenKey).get();
        return StringUtils.isNotNull(refreshToken) ? refreshToken.toString() : null;
    }

}
